﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Mail;
using System.Net;
using Musicman.Common;
using System.Runtime.Remoting.Contexts;
using System.Runtime.CompilerServices;
using System.Threading;
using System.IO;

namespace Musicman.Utilities
{
    public class MailSender
    {
        # region singleton definition
        static readonly MailSender instance = new MailSender();

        public static MailSender Instance
        {
            get
            {
                return instance;
            }
        }
        static MailSender()
        {
            try
            {
                instance.client = new SmtpClient(AppSettingsHelper.GetWebConfigValue(Constants.SmtpServer),
                                                 Int32.Parse(AppSettingsHelper.GetWebConfigValue(Constants.SmtpServerPort)));
                instance.client.UseDefaultCredentials = false;
                instance.client.Credentials = new NetworkCredential(AppSettingsHelper.GetWebConfigValue(Constants.SendUsername),
                                                                    AppSettingsHelper.GetWebConfigValue(Constants.SendPassword));
                instance.client.EnableSsl = Boolean.Parse(AppSettingsHelper.GetWebConfigValue(Constants.SmtpuseSSL));
                instance.queuedMessages = new Queue<MailMessage>();
            }
            catch (Exception ex)
            {
                LogManager.LogException("unable to create mail sender", ex);
                instance = null;
            }
        }
        #endregion

        private SmtpClient client;
        private Queue<MailMessage> queuedMessages;
        private bool sending = false;
        public object locker = new object();

        public void SendMailAsync(MailMessage mail)
        {
            if (sending)
            {
                lock (locker)
                {
                    queuedMessages.Enqueue(mail);
                }
            }
            else
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(SendMail), mail);
            }
        }

        [MethodImplAttribute(MethodImplOptions.Synchronized)]
        public void SendMail(object mailObj)
        {
            sending = true;
            MailMessage mail = (MailMessage)mailObj;
            try
            {
                client.Send(mail);
                mail.Dispose();
            }
            catch (Exception ex)
            {
                LogManager.LogException("error sending mail", ex);
            }
            sending = false;
            MailMessage mm = null;
            lock (locker)
            {
                if (queuedMessages.Count != 0)
                {
                    mm = queuedMessages.Dequeue();
                }
            }
            if (mm != null)
            {
                SendMail(mm);
            }
        }
    }
}
